package Builder; import java.awt.event.MouseWheelEvent; import org.eclipse.swt.events.MouseEvent; import Common.Matrix4; import Common.Ray3; import Common.Vector2f; import Common.Vector3f; import LDraw.Support.LDrawGLCamera; import LDraw.Support.MatrixMath; import LDraw.Support.type.ProjectionModeT; public class MainCamera extends LDrawGLCamera { private int mouseXStart; private int mouseYStart; private float currentCameraRotateX; private float currentCameraRotateY; private float startCameraRotateX; private float startCameraRotateY; private float distanceBetweenObjectToCamera; private float screenWidth = 1.0f; private float screenHeight = 1.0f; private Matrix4 modelViewMatrix; private Matrix4 projectionMatrix; private Vector3f lookAtPos = new Vector3f(0, 0, 0); public MainCamera() { super(); setDefault(); } public Vector3f getLookAtPos() { return new Vector3f(lookAtPos); } public Matrix4 getModelViewMatrix() { return modelViewMatrix; } public Matrix4 getProjectionMatrix() { return projectionMatrix; } public Matrix4 getTransformMatrix() { return Matrix4.multiply(modelViewMatrix, projectionMatrix); } public void setDefault() { currentCameraRotateX = (float) (Math.PI); currentCameraRotateY = -0.52f; startCameraRotateX = 0.0f; startCameraRotateY = 0.0f; distanceBetweenObjectToCamera = 850.0f; } public void moveTo(Vector3f lookat) { lookAtPos = new Vector3f(lookat); makeModelView(); } public Vector3f screenToWorldXZ(float mouse_x, float mouse_y, float planeY) { float normalised_x = -(2 * mouse_x / screenWidth - 1); float normalised_y = -(1 - 2 * mouse_y / screenHeight); normalised_x /= projectionMatrix.getElement(0, 0); normalised_y /= projectionMatrix.getElement(1, 1); Matrix4 invView = null; invView = Matrix4.inverse(modelViewMatrix); Vector3f dir = new Vector3f(-(normalised_x * invView.getElement(0, 0) + normalised_y * invView.getElement(1, 0) + invView.getElement( 2, 0)), -(normalised_x * invView.getElement(0, 1) + normalised_y * invView.getElement(1, 1) + invView.getElement( 2, 1)), -(normalised_x * invView.getElement(0, 2) + normalised_y * invView.getElement(1, 2) + invView.getElement( 2, 2))); Vector3f cameraPos = new Vector3f(invView.getElement(3, 0), invView.getElement(3, 1), invView.getElement(3, 2)); Vector3f pickPos = Vector3f.intersectRayPlane(cameraPos, dir, new Vector3f(1, planeY, 0), new Vector3f(0, planeY, 0), new Vector3f(0, planeY, 1)); return pickPos; } public Vector3f screenToWorldXY(float mouse_x, float mouse_y, float planeZ) { float normalised_x = -(2 * mouse_x / screenWidth - 1); float normalised_y = -(1 - 2 * mouse_y / screenHeight); normalised_x /= projectionMatrix.getElement(0, 0); normalised_y /= projectionMatrix.getElement(1, 1); Matrix4 invView = null; invView = Matrix4.inverse(modelViewMatrix); Vector3f dir = new Vector3f(-(normalised_x * invView.getElement(0, 0) + normalised_y * invView.getElement(1, 0) + invView.getElement( 2, 0)), -(normalised_x * invView.getElement(0, 1) + normalised_y * invView.getElement(1, 1) + invView.getElement( 2, 1)), -(normalised_x * invView.getElement(0, 2) + normalised_y * invView.getElement(1, 2) + invView.getElement( 2, 2))); Vector3f cameraPos = new Vector3f(invView.getElement(3, 0), invView.getElement(3, 1), invView.getElement(3, 2)); Vector3f pickPos = Vector3f.intersectRayPlane(cameraPos, dir, new Vector3f(1, 0, planeZ), new Vector3f(0, 1, planeZ), new Vector3f(-1, 0, planeZ)); return pickPos; } public Ray3 getRay(float mousex, float mousey) { float normalised_x = -(2 * mousex / screenWidth - 1); float normalised_y = -(1 - 2 * mousey / screenHeight); normalised_x /= projection[0]; normalised_y /= projection[5]; Matrix4 invView = MatrixMath.Matrix4CreateFromGLMatrix4(modelView); invView.invert(); Ray3 retRay = new Ray3(); retRay.setDirection(new Vector3f(-(normalised_x * invView.getElement(0, 0) + normalised_y * invView.getElement(1, 0) + invView.getElement(2, 0)), -(normalised_x * invView.getElement(0, 1) + normalised_y * invView.getElement(1, 1) + invView.getElement(2, 1)), -(normalised_x * invView.getElement(0, 2) + normalised_y * invView.getElement(1, 2) + invView.getElement(2, 2)))); retRay.setOrigin(new Vector3f(invView.getElement(3, 0), invView .getElement(3, 1), invView.getElement(3, 2))); float magnitude = (float) Math .sqrt(Math.pow(retRay.getDirection().x, 2) + Math.pow(retRay.getDirection().y, 2) + Math.pow(retRay.getDirection().z, 2)); retRay.getDirection().setX(retRay.getDirection().x / magnitude); retRay.getDirection().setY(retRay.getDirection().y / magnitude); retRay.getDirection().setZ(retRay.getDirection().z / magnitude); return retRay; } public void setDistanceBetweenObjectToCamera(float distance) { this.distanceBetweenObjectToCamera = distance; makeModelView(); } public float getDistanceBetweenObjectToCamera() { return this.distanceBetweenObjectToCamera; } public void setCurrentCameraRotation(Vector3f rotation) { this.currentCameraRotateX = rotation.getX(); this.currentCameraRotateY = rotation.getY(); makeModelView(); } public void setScreenSize(final float width, final float height) { screenWidth = width; screenHeight = height; } public void makeModelView() { Matrix4 m = new Matrix4(); m.setIdentity(); m.rotateY(currentCameraRotateX); m.rotateX(currentCameraRotateY); Vector3f veye = new Vector3f(0, 0, distanceBetweenObjectToCamera); Vector3f vup = new Vector3f(0, -1, 0); Vector3f vcenter = new Vector3f(0, 0, 0); veye = m.multiply(veye); vup = m.multiply(vup); veye = lookAtPos.add(veye); vcenter = lookAtPos.add(vcenter); Matrix4 temp = new Matrix4(); temp.makeLookAtMatrix(veye, vcenter, vup); if (modelViewMatrix != null) synchronized (modelViewMatrix) { modelViewMatrix = temp; } else { modelViewMatrix = temp; } for (int i = 0; i < 16; i++) { modelView[i] = modelViewMatrix.getElement(i / 4, i % 4); } } public void makeProjection() { if (projectionMode == ProjectionModeT.ProjectionModePerspective) { projectionMatrix = new Matrix4(); float aspect = screenWidth / screenHeight; projectionMatrix.makePerspectiveMatrix(45, aspect, 20, 20000); for (int i = 0; i < 16; i++) { projection[i] = projectionMatrix.getElement(i / 4, i % 4); } } } public void startRotate(int x, int y) { // TODO Auto-generated method stub mouseXStart = x; mouseYStart = y; startCameraRotateX = currentCameraRotateX; startCameraRotateY = currentCameraRotateY; } public void rotate(int x, int y) { // TODO Auto-generated method stub int mouseX = mouseXStart - x; int mouseY = mouseYStart - y; currentCameraRotateX = startCameraRotateX + (((float) mouseX) / 100.0f); currentCameraRotateY = startCameraRotateY + (((float) mouseY) / 100.0f); // System.out.println("mouseDragged "+currentCameraRotateX +" " + // currentCameraRotateY ); makeModelView(); } public void zoom(MouseEvent e) { // TODO Auto-generated method stub if (e.count > 0) { distanceBetweenObjectToCamera -= 30.0; if (distanceBetweenObjectToCamera < 1.0f) distanceBetweenObjectToCamera = 1.0f; } else { distanceBetweenObjectToCamera += 30.0; if (distanceBetweenObjectToCamera > 4000.0f) distanceBetweenObjectToCamera = 4000.0f; } if (Float.isNaN(distanceBetweenObjectToCamera)) distanceBetweenObjectToCamera = 0; makeModelView(); } public Vector2f getWorldToScreenPos(Vector3f worldPos) { return getWorldToScreenPos(worldPos, true); } public Vector2f getWorldToScreenPos(Vector3f worldPos, boolean depthTest) { Vector3f pos = null; pos = modelViewMatrix.transformPoint(worldPos); if (depthTest && pos.z > 0f) return null; else { final float value = 1.2f * screenHeight / -pos.z; pos.x = pos.x * value; pos.y = pos.y * value; } return new Vector2f(pos.x, pos.y); // System.out.println(pos); // screenRatio width/height } public float getScreenToWorldDistance(float distance){ Vector3f pos = null; pos = modelViewMatrix.getDefaultTransformPos(); if (pos.z > 0f) return 0; return distance/1.2f / screenHeight*-pos.z; } }